Vercel

Handling Integrations

Learn how to handle integration requests and follow-up script permissions in the v0 API

Learn how to handle integration requests when a v0 chat pauses and needs input from your app. The short version is:

  1. Prompt the agent.
  2. Inspect the latest assistant message and read the chat's vercelProjectId.
  3. Install the integration with the Vercel API.
  4. Confirm the install with POST /v2/chats/{chatId}/messages/resolve.
  5. Handle script permissions if the agent asks for them next.

This guide focuses on the integration flow. For the full task schema, see Resolve Task.

1. Prompt the agent

Start or continue a chat with a request that depends on an integration.

For example:

  • "Build a waiting list app with Neon."
  • "Create a dashboard that uses Supabase auth."

If the agent can continue without extra setup, it will. If it needs an integration, it will stop and ask your app to handle it.

2. Inspect the latest assistant message

When a chat is blocked on integration setup, inspect the latest assistant message first. Fetch it with:

  • GET /v2/chats/{chatId}/messages/{messageId}

An integration request surfaces as an agent-action part in the message's parts array with name: "get_or_request_integration". Its data.requestedIntegrations lists the integration names to install (for example, ["Neon"]), and data.requestedMcpPresets lists any MCP presets. You pass these values back in step 4. The message content also describes the request in prose.

Use the latest blocked assistant message only. If you try to resolve an older task after the chat has moved on, resolve-task returns 409 Conflict.

3. Install the integration with the Vercel API

Once you know which integration the assistant is asking for, install or connect it in Vercel.

Use the chat's vercelProjectId for the project-scoped Vercel API calls in this step. In the beta chat response types, vercelProjectId is the linked Vercel project ID. Do not use projectId here. projectId is the separate v0 project ID, and it is deprecated in the chat response.

import { v0 } from 'v0'

const chat = await v0.chats.get({
  chatId: '123',
})

if (!chat.vercelProjectId) {
  throw new Error('This chat is not linked to a Vercel project yet.')
}

const vercelProjectId = chat.vercelProjectId

This step happens outside the v0 API. The exact Vercel API calls depend on your integration flow, but these docs are the relevant starting points:

When you call the Vercel endpoint that connects a resource to a project, pass vercelProjectId from the chat.

After the integration is actually connected, return to the v0 chat and confirm it with resolve-task.

4. Confirm the install with resolve-task

Use task.type: "confirmed-steps" after the integration is installed. Pass the integration names exactly as the assistant requested them, such as Neon or Supabase.

import { v0 } from 'v0'

await v0.messages.resolve({
  chatId: '123',
  task: {
    type: 'confirmed-steps',
    connectedIntegrationNames: ['Neon'],
  },
})

If you are rejecting the integration request instead of approving it, pass an empty array:

{
  "task": {
    "type": "confirmed-steps",
    "connectedIntegrationNames": []
  }
}

You can also confirm other setup work with the same task type, including MCP presets, scripts, and environment variables.

5. Handle script permissions if needed

After the integration is connected, the assistant may ask for permission to run follow-up scripts, such as database setup or migrations.

When that happens, inspect the latest assistant message again. The pending action surfaces as a tool-call part in the message's parts array. While the agent is waiting for your approval, that part includes a suggestedPermissions array.

To approve the request, call resolve with task.type: "confirmed-permissions" and pass the suggestedPermissions objects back unchanged as task.permissions.

The submitted permissions must match the ones currently pending on the latest blocked assistant message, or resolve returns 409 Conflict.

{
  "task": {
    "type": "confirmed-permissions",
    "permissions": [
      {
        "type": "ALLOW_DYNAMIC_TOOL_STRICT",
        "toolName": "SystemAction",
        "input": {
          "systemAction": "executeScript",
          "executeScript": "/scripts/setup-db.sql"
        }
      }
    ]
  }
}

To reject the request, ignore the permission request and send any other follow-up message.

Example Flow

Here is the full flow in plain English:

  1. Your app prompts v0 to build something that needs Neon.
  2. The assistant stops and asks for the Neon integration, surfaced as a get_or_request_integration agent-action part.
  3. Your backend reads vercelProjectId from GET /v2/chats/{chatId} and uses that value in the Vercel API calls that connect Neon.
  4. Your backend calls POST /v2/chats/{chatId}/messages/resolve with connectedIntegrationNames: ["Neon"].
  5. The assistant resumes. If it needs to run a migration script, it stops again with a tool-call part that carries suggestedPermissions.
  6. Your backend passes those suggestedPermissions back in a confirmed-permissions task to approve.

That is the complete pattern for handling integrations in the Platform API.